<template>
  <div>
    <span @click="onShowAddCostModal">
      <slot></slot>
    </span>

    <el-drawer
      v-model="addCostModalVisible"
      size="80%"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      append-to-body
    >
      <template #header>
        <div class="header">
          <span v-if="!props.workId && props.feeId" class="text">审核费用</span>
          <span v-else class="text">新增服务项目</span>
        </div>
      </template>
      <div class="info_form_content" v-if="!props.workId && props.feeId">
        <div class="info">
          <div class="item">
            <div class="label">费用单号:</div>
            <div class="value">{{ feeNo }}</div>
          </div>
          <div class="item">
            <div class="label">审核状态:</div>
            <div class="value">
              <HStatus :height="22" type="warning">待审核</HStatus>
            </div>
          </div>
          <div class="item">
            <div class="label">工单单号:</div>
            <div class="value"> {{ workNo }} </div>
          </div>
        </div>
        <div class="reamrk">
          <div class="label">审核备注:</div>
          <div class="value">
            <el-input
              v-model="tableDataList.remark"
              clearable
              maxlength="200"
              placeholder="填写备注信息"
              show-word-limit
              type="textarea"
              resize="both"
            />
          </div>
        </div>
      </div>
      <div class="table" v-loading="applyOrCheckLoading">
        <el-table
          border
          stripe
          resizable
          :data="tableDataList.feeDetails"
          :row-class-name="tableRowClassName"
          @cell-mouse-enter="onCellMouseEnter"
          @cell-mouse-leave="onCellMouseLeave"
        >
          <!-- 操作 -->
          <el-table-column label="操作" width="70" type="index" fixed="left" align="center">
            <template #default="scope">
              <template v-if="!props.workId && props.feeId">
                {{ scope.$index + 1 }}
              </template>
              <template v-else>
                <div v-show="styleColumn[scope.$index].tableColumnIndex" :rowIndex="scope.$index">
                  <span>{{ scope.$index + 1 }}</span>
                </div>
                <div v-show="styleColumn[scope.$index] && styleColumn[scope.$index].tableColumnBtn">
                  <span class="operation">
                    <el-icon @click="onAddFeeProject" color="#007cff" size="16" class="icon">
                      <CirclePlus />
                    </el-icon>
                    <el-icon
                      color="rgba(245, 108, 108, 1)"
                      size="16"
                      class="icon"
                      @click="deleteItem(scope.$index)"
                      v-show="tableDataList.feeDetails.length > 1"
                    >
                      <RemoveFilled />
                    </el-icon>
                  </span>
                </div>
              </template>
            </template>
          </el-table-column>

          <!--审核状态-->
          <el-table-column
            v-if="!props.workId && props.feeId"
            label="审核状态"
            show-overflow-tooltip
            width="120"
          >
            <template #default="scope">
              <el-select v-model="scope.row.status" filterable placeholder="审核状态">
                <el-option
                  v-for="item in checkStatusOptions"
                  :key="item.name"
                  :label="item.name"
                  :value="item.value"
                />
              </el-select>
            </template>
          </el-table-column>

          <!-- 收支类型 -->
          <el-table-column label="收支类型" width="150">
            <template #default="scope">
              <el-select
                placeholder="收支类型"
                @change="onChangeIncomeOrPayType(scope.$index)"
                v-model="scope.row.type"
                filterable
              >
                <el-option
                  v-for="item in incomeOrPayTypeOptional"
                  :value="item.value"
                  :key="item.value"
                  :label="item.name"
                />
              </el-select>
            </template>
          </el-table-column>

          <!-- 费用项目 -->
          <el-table-column label="费用项目" width="150" show-overflow-tooltip>
            <template #default="scope">
              <el-select
                placeholder="请选择"
                filterable
                v-model="scope.row.workFeeProjectId"
                :filter-method="handleGetFeeProjectOptions"
                :loading="loading"
                remote-show-suffix
              >
                <el-option
                  v-for="item in modules"
                  :key="item.name"
                  @click="handleChangeFeeProject(item, scope.$index)"
                  :value="item.id"
                  :label="item.name"
                />
              </el-select>
            </template>
          </el-table-column>

          <!-- 申请数量 -->
          <!-- <el-table-column show-overflow-tooltip label="申请数量" width="100">
            <template #default="scope">
              <el-input
                @input="scope.row.qty = scope.row.qty.replace(/\D/g, '')"
                v-model="scope.row.qty"
                placeholder="数量"
              />
            </template>
          </el-table-column> -->

          <!-- 向服务商支付费用单价 -->
          <el-table-column label="支付服务商费用" width="150">
            <template #default="scope">
              <el-input
                clearable
                v-model="scope.row.payNetworkPrice"
                @keyup="(e: Event) => handlePayNetworkPricePriceInput(e, scope.$index)"
                style="border-radius: 2px"
              >
                <template #prepend>￥</template>
              </el-input>
            </template>
          </el-table-column>

          <!-- 收取商家费用单价 -->
          <el-table-column label="收取商家费用" width="140">
            <template #default="{ row, $index }">
              <el-input
                clearable
                v-model="row.receiveFactoryPrice"
                :disabled="row.type !== 1"
                @keyup="(e: Event) => handleReceiveFactoryPriceInput(e, $index)"
                style="border-radius: 2px"
              >
                <template #prepend>￥</template>
              </el-input>
            </template>
          </el-table-column>

          <!-- 平台承担费用单价 -->
          <el-table-column label="平台承担费用单价" width="140">
            <template #default="{ row, $index }">
              <el-input
                clearable
                v-model="row.price"
                :disabled="row.type !== 2"
                @keyup="(e: Event) => handlePriceInput(e, $index)"
                style="border-radius: 2px"
              >
                <template #prepend>￥</template>
              </el-input>
            </template>
          </el-table-column>

          <!-- 附件 -->
          <el-table-column show-overflow-tooltip label="备注" min-width="140" max-width="150">
            <template #default="scope">
              <el-input v-model="scope.row.remark" clearable placeholder="填写备注" />
            </template>
          </el-table-column>

          <!-- 备注 -->
          <el-table-column label="附件(最多上传8个)" width="460">
            <template #default="scope">
              <div class="updata_pic">
                <el-dropdown v-for="(img, index) in scope.row.images" :key="index">
                  <el-image
                    class="img"
                    style="width: 40px; height: 40px"
                    :src="img.image"
                    :initial-index="index"
                    :preview-src-list="scope.row.images.map((item) => item.image)"
                    fit="scale-down"
                    preview-teleported
                  />
                  <template #dropdown v-if="!img.id">
                    <el-dropdown-menu>
                      <el-dropdown-item @click="handleDelFile(scope.$index, index)"
                        >删除</el-dropdown-item
                      >
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
                <el-upload
                  action="#"
                  v-if="scope.row.images.length < 8"
                  multiple
                  list-type="picture-card"
                  accept="image/*"
                  :auto-upload="false"
                  :show-file-list="false"
                  :on-change="(file: UploadFile) => handleAddFile(file, scope.$index)"
                >
                  <div class="plus_add">
                    <el-icon size="12">
                      <Plus />
                    </el-icon>
                  </div>
                </el-upload>
              </div>
            </template>
          </el-table-column>
        </el-table>
      </div>

      <template #footer>
        <div class="btns flex-justify-end" style="gap: 10px">
          <HButton is-modal @click="onSaveBtn" type="primary" :loading="applyOrCheckLoading">{{
            props.feeId ? '保存' : '提交申请'
          }}</HButton>
          <HButton is-modal @click="onClose" :loading="applyOrCheckLoading">取消</HButton>
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<script lang="ts" setup>
  import { onMounted, ref } from 'vue'
  import {
    checkOrderFee,
    feeSaveOrder,
    OrderFeeDetailProjectInfo,
    workFeeProjectPageSelect,
  } from '@/api/order'
  import { orderAnnexUpload } from '@/api/upload'
  import { ElMessage, UploadFile } from 'element-plus'
  import { checkNum, keepPartInteger } from '@/utils/validate'
  import { CirclePlus, Plus, RemoveFilled } from '@element-plus/icons-vue'
  import _ from 'lodash'
  import { OrderAPIRequestParam } from '@/typings/api/order'
  import {
    ApplyOrCheckFeeResponse,
    FeeProjectOptions,
  } from '@/components/pages/order/detail/ServiceFee/ApplyOrCheckFeeModal/types'
  import HButton from '@/components/common/button/HButton.vue'
  import HStatus from '@/components/common/status/HStatus.vue'

  // 如果有传feeId就是审核费用，否则就是申请费用
  const props = defineProps({
    workId: String,
    feeId: String,
    workNo: String,
    feeNo: String,
  })

  const emits = defineEmits<{
    (e: 'update-list'): void
  }>()

  // 审核状态下拉选项
  const checkStatusOptions = [
    { name: '已通过', value: 2 },
    { name: '已驳回', value: 3 },
  ]

  // 添加费用弹窗显示状态
  const addCostModalVisible = ref(false)

  // 费用项目
  const modules = ref<Array<FeeProjectOptions>>([])

  const loading = ref(false)
  const styleColumn = ref([
    {
      tableColumnBtn: false,
      tableColumnIndex: true,
    },
  ])

  // 收支类型选项
  const incomeOrPayTypeOptional = [
    { name: '商家承担', value: 1 },
    { name: '平台承担', value: 2 },
  ]

  // 服务项目 - 请求参数
  const tableDataList = ref<OrderAPIRequestParam.SaveOrUpdateOrderFee>({
    id: null, // 工单服务费用申请ID，新增不必传，修改必传
    workId: null, // 工单ID
    remark: '', //	审核备注
    feeDetails: [
      {
        delImageIds: [], //删除的工单费用图片对象ID
        id: null, // 费用项目详情ID，新增不必传，修改必传
        images: [], // 工单服务费用图片对象
        payNetworkPrice: 0, // 向服务商支付费用
        price: 0, // 平台承担费用
        qty: 1, // 数量
        receiveFactoryPrice: 0, // 收取商家费用
        remark: '', // 备注
        type: 1, //	收支类型：1-品牌商家承担，2-平台承担
        workFeeProjectId: null, // 工单费用项目ID
      },
    ],
  })

  // 给row对象赋索引值，注：在此赋值后，才可以在其他用到row的地址取值
  const tableRowClassName = ({ row, rowIndex }) => {
    row.index = rowIndex
  }
  // 鼠标移入事件
  const onCellMouseEnter = (row) => {
    styleColumn.value[row.index] && (styleColumn.value[row.index].tableColumnBtn = true)
    styleColumn.value[row.index] && (styleColumn.value[row.index].tableColumnIndex = false)
  }
  // 鼠标移出事件
  const onCellMouseLeave = (row) => {
    styleColumn.value[row.index] && (styleColumn.value[row.index].tableColumnBtn = false)
    styleColumn.value[row.index] && (styleColumn.value[row.index].tableColumnIndex = true)
  }

  /**
   * 添加费用项目
   */
  function onAddFeeProject() {
    tableDataList.value.feeDetails.push({
      delImageIds: [], //删除的工单费用图片对象ID
      id: null, // 费用项目详情ID，新增不必传，修改必传
      images: [], // 工单服务费用图片对象
      payNetworkPrice: '0', // 向服务商支付费用
      price: '0', // 平台承担费用
      qty: 1, // 数量
      receiveFactoryPrice: '0', // 收取商家费用
      remark: '', // 备注
      type: 1, //	收支类型：1-品牌商家承担，2-平台承担
      workFeeProjectId: null, // 工单费用项目ID
    })
    styleColumn.value.push({
      tableColumnIndex: true,
      tableColumnBtn: false,
    })
  }

  // 新增删除
  function deleteItem(n: number) {
    if (tableDataList.value.feeDetails.length == 1) {
      return
    }
    tableDataList.value.feeDetails = tableDataList.value.feeDetails.filter((o, index) => {
      return index != n
    })
    styleColumn.value.splice(n, 1)
  }

  // 申请或审核加载
  const applyOrCheckLoading = ref(false)

  /**
   * 保存按钮点击事件
   */
  async function onSaveBtn() {
    applyOrCheckLoading.value = true
    let checkResult = true
    for (let i = 0; i < tableDataList.value.feeDetails.length; i++) {
      if (!String(tableDataList.value.feeDetails[i].payNetworkPrice)) {
        ElMessage({
          type: 'error',
          message: `请输入第${i + 1}行的向服务商支付费用单价`,
        })
        checkResult = false
        break
      }

      if (
        !String(tableDataList.value.feeDetails[i].receiveFactoryPrice) &&
        tableDataList.value.feeDetails[i].type === 1
      ) {
        ElMessage({
          type: 'error',
          message: `请输入第${i + 1}行的收取商家费用单价`,
        })
        checkResult = false
        break
      }
    }

    if (checkResult) {
      // 上传文件
      for (const key in tableDataList.value.feeDetails) {
        let imgobj = tableDataList.value.feeDetails[key]
        let arrimg = []
        if (imgobj.images.length > 0) {
          for (const i in imgobj.images) {
            arrimg.push(imgobj.images[i].file)
          }
          if (imgobj.images[0].file) {
            const res = await orderAnnexUpload(arrimg)
            imgobj.images = res.data.data.rows.map((o: string) => ({ id: null, image: o }))
          }
        }
      }

      // 删除images中的file字段
      tableDataList.value.feeDetails = tableDataList.value.feeDetails.map((feeDetail) => {
        const __feeDetail = feeDetail
        __feeDetail.images = __feeDetail.images.map((image) => {
          const __image = image
          delete __image.file
          return __image
        })
        return __feeDetail
      })

      let res: ApplyOrCheckFeeResponse | null = null
      if (!props.workId && props.feeId) {
        res = await checkOrderFee(tableDataList.value)
      } else {
        tableDataList.value.workId = props.workId
        res = await feeSaveOrder(tableDataList.value)
      }
      if (res && res.data.success) {
        ElMessage({
          showClose: true,
          message: res.data.message,
          type: 'success',
          offset: 200,
        })
        emits('update-list')
        addCostModalVisible.value = false
        tableDataList.value = {
          id: null, // 工单服务费用申请ID，新增不必传，修改必传
          workId: null, // 工单ID
          remark: '', //	审核备注
          feeDetails: [
            {
              delImageIds: [], //删除的工单费用图片对象ID
              id: null, // 费用项目详情ID，新增不必传，修改必传
              images: [], // 工单服务费用图片对象
              payNetworkPrice: 0, // 向服务商支付费用
              price: 0, // 平台承担费用
              qty: 1, // 数量
              receiveFactoryPrice: 0, // 收取商家费用
              remark: '', // 备注
              type: 1, //	收支类型：1-品牌商家承担，2-平台承担
              workFeeProjectId: null, // 工单费用项目ID
            },
          ],
        }
      } else {
        if (res.data.isError)
          ElMessage({
            showClose: true,
            message: res.data.message,
            duration: 4000,
            offset: 200,
            type: 'error',
          })
      }
    }
    applyOrCheckLoading.value = false
  }

  /**
   * 获取费用详情
   * @param {number} index - 索引
   */
  const getFeeDetail = (index: number) => {
    return tableDataList.value.feeDetails[index]
  }

  /**
   * 费用项目选择事件
   * @param {Object} item - 费用项目
   * @param {number} index - 当前操作的表格行的索引
   */
  function handleChangeFeeProject(item: FeeProjectOptions, index: number) {
    /**
     * 收支类型是商家承担
     * 将费用项目的金额填充到收取商家费用
     * 将费用项目的金额填充到收取向服务商支付费用
     */
    if (getFeeDetail(index).type === 1 && !props.feeId) {
      tableDataList.value.feeDetails[index].receiveFactoryPrice = item.price
      tableDataList.value.feeDetails[index].payNetworkPrice = item.price
    }

    /**
     * 收支类型是平台承担
     * 将费用项目的金额填充到平台承担费用
     */
    if (getFeeDetail(index).type === 2 && !props.feeId) {
      tableDataList.value.feeDetails[index].price = item.price
      tableDataList.value.feeDetails[index].payNetworkPrice = item.price
    }
  }

  // 获取费用项目下拉选项请求参数
  const getFeeProjectOptionsParam = ref({
    limit: 0,
    name: '',
    page: 0,
  })

  /**
   * 费用项目下拉数据
   */
  const handleGetFeeProjectOptions = _.throttle((query: string) => {
    if (getFeeProjectOptionsParam.value.name === query) {
      return false
    }
    getFeeProjectOptionsParam.value.name = query
    getFeeProjectOptionsFn()
  }, 500)

  /**
   * 获取费用项目选项方法
   */
  const getFeeProjectOptionsFn = async () => {
    loading.value = true
    const res = await workFeeProjectPageSelect(getFeeProjectOptionsParam.value)
    if (res.data.success) {
      modules.value = res.data.data.rows
    } else {
      if (res.data.isError)
        ElMessage({
          showClose: true,
          message: res.data.message,
          duration: 4000,
          offset: 200,
          type: 'error',
        })
    }
    loading.value = false
  }

  /**
   * 添加图片或pdf
   * @param {Object} file - 文件
   * @param {number} index - 当前操作的表格行的索引
   */
  const handleAddFile = async (file: UploadFile, index: number) => {
    if (!['image/png', 'image/jpg', 'image/jpeg'].includes(file.raw.type)) {
      imgType()
      return
    }
    if (tableDataList.value.feeDetails[index].images.length >= 8) {
      onExceed()
      return
    }
    tableDataList.value.feeDetails[index].images.push({
      file: file.raw,
      image: URL.createObjectURL(file.raw),
    })
  }
  const imgType = _.debounce(() => {
    ElMessage({
      type: 'error',
      message: '只能上传图片类型的文件',
    })
  }, 20)
  const onExceed = _.debounce(() => {
    ElMessage({
      type: 'error',
      message: '上传的数量不能超过8个',
    })
  }, 10)
  /**
   * 删除文件
   * @param {number} rowIndex - 操作的表格行的索引
   * @param {number} imgIndex - 文件索引
   */
  const handleDelFile = (rowIndex: number, imgIndex: number) => {
    if (tableDataList.value.feeDetails[rowIndex].images[imgIndex].id) {
      ElMessage({
        type: 'error',
        message: '禁止删除原本附件',
      })
      return
    }
    const imgs = tableDataList.value.feeDetails[rowIndex].images.splice(imgIndex, 1)
    tableDataList.value.feeDetails[rowIndex].delImageIds.push(imgs[0].id)
  }

  /**
   * 显示申请费用弹窗
   */
  const onShowAddCostModal = async () => {
    if (props.feeId) {
      tableDataList.value.id = props.feeId
      await getOrderFeeDetailProjectInfo(props.feeId)
    }
    await getFeeProjectOptionsFn()
    addCostModalVisible.value = true
  }

  /**
   * 收支类型改变
   * @param {number} index - 操作的表格行的索引
   */
  const onChangeIncomeOrPayType = (index: number) => {
    // 提取费用项目的金额
    let price = 0
    if (tableDataList.value.feeDetails[index].workFeeProjectId) {
      const feeProject = modules.value.find(
        (module) => module.id === tableDataList.value.feeDetails[index].workFeeProjectId,
      )
      price = feeProject.price
    }

    /**
     * 收支类型是商家承担
     * 将费用项目的金额填充到收取商家费用
     * 将费用项目的金额填充到向服务商支付费用
     * 将平台承担费用的金额清零
     */
    if (getFeeDetail(index).type === 1 && !props.feeId) {
      tableDataList.value.feeDetails[index].receiveFactoryPrice = price
      tableDataList.value.feeDetails[index].payNetworkPrice = price
      tableDataList.value.feeDetails[index].price = 0
    }

    /**
     * 收支类型是平台承担
     * 将费用项目的金额填充到平台承担费用
     * 将费用项目的金额填充到服务商支付费用
     * 将收取商家费用的金额清零
     */
    if (getFeeDetail(index).type === 2 && !props.feeId) {
      tableDataList.value.feeDetails[index].price = price
      tableDataList.value.feeDetails[index].payNetworkPrice = price
      tableDataList.value.feeDetails[index].receiveFactoryPrice = 0
    }
  }

  /**
   * 收取商家费用输入框输入事件
   * @param {Event} e - input输入元素
   * @param {number} index - 表格操作的行的索引
   */
  const handleReceiveFactoryPriceInput = (e: Event, index: number) => {
    checkNum(e)

    // 防止输入频繁输入会出现三位小数的问题
    tableDataList.value.feeDetails[index].receiveFactoryPrice = (e.target as HTMLInputElement).value

    // 限制金额的最大值为9999999999.99
    ;(e.target as HTMLInputElement).value = keepPartInteger(
      (e.target as HTMLInputElement).value,
      10,
    )
  }

  /**
   * 向服务商支付费用输入框输入事件
   * @param {Event} e - Event
   * @param {number} index - 表格操作的行的索引
   */
  const handlePayNetworkPricePriceInput = (e: Event, index: number) => {
    checkNum(e)

    // 防止输入频繁输入会出现三位小数的问题
    tableDataList.value.feeDetails[index].payNetworkPrice = (e.target as HTMLInputElement).value

    // 限制金额的最大值为9999999999.99
    ;(e.target as HTMLInputElement).value = keepPartInteger(
      (e.target as HTMLInputElement).value,
      10,
    )
  }

  /**
   * 平台承担费用
   * @param {Event} e - Event
   * @param {number} index - 表格操作的行的索引
   */
  const handlePriceInput = (e: Event, index: number) => {
    checkNum(e)

    // 防止输入频繁输入会出现三位小数的问题
    tableDataList.value.feeDetails[index].price = (e.target as HTMLInputElement).value

    // 限制金额的最大值为9999999999.99
    ;(e.target as HTMLInputElement).value = keepPartInteger(
      (e.target as HTMLInputElement).value,
      10,
    )
  }

  /**
   * 获取详情，只有审核时才会用到这个方法
   * @param {string} id - 费用id
   */
  const getOrderFeeDetailProjectInfo = async (id: string) => {
    const res = await OrderFeeDetailProjectInfo(id)
    if (res.data.success) {
      tableDataList.value.feeDetails = res.data.data.row.map((o) => {
        o.status = o.status == 1 ? 2 : o.status
        return { ...o, statusType: o.status, delImageIds: [] }
      })
    } else {
      if (res.data.isError)
        ElMessage({
          showClose: true,
          message: res.data.message,
          duration: 4000,
          type: 'error',
        })
    }
  }

  /**
   * 关闭事件
   */
  const onClose = () => {
    tableDataList.value = {
      id: null, // 工单服务费用申请ID，新增不必传，修改必传
      workId: null, // 工单ID
      remark: '', //	审核备注
      feeDetails: [
        {
          delImageIds: [], //删除的工单费用图片对象ID
          id: null, // 费用项目详情ID，新增不必传，修改必传
          images: [], // 工单服务费用图片对象
          payNetworkPrice: 0, // 向服务商支付费用
          price: 0, // 平台承担费用
          qty: 1, // 数量
          receiveFactoryPrice: 0, // 收取商家费用
          remark: '', // 备注
          type: 1, //	收支类型：1-品牌商家承担，2-平台承担
          workFeeProjectId: null, // 工单费用项目ID
        },
      ],
    }
    addCostModalVisible.value = false
  }

  onMounted(async () => {
    if (props.feeId) {
      tableDataList.value.id = props.feeId
      await getOrderFeeDetailProjectInfo(props.feeId)
    }
  })
</script>

<style lang="scss" scoped>
  @import './ApplyOrCheckFeeModal.scss';
</style>
